﻿#pragma once

#include "../MirEnvir/Envir.h"
#include "../../Shared/Enums.h"
#include "../../Shared/Data/ItemData.h"
#include "MagicInfo.h"
#include "../MirObjects/MapObject.h"
#include "MailInfo.h"
#include "QuestProgressInfo.h"
#include "../../Shared/Globals.h"
#include "AccountInfo.h"
#include "../MirObjects/PlayerObject.h"
#include "../MirNetwork/MirConnection.h"
#include "../../Shared/ClientPackets.h"
#include "../../Shared/Data/SharedData.h"
#include "../MirObjects/MonsterObject.h"
#include "../../Shared/Data/ClientData.h"
#include "../../Shared/Data/IntelligentCreatureData.h"
#include "../../Shared/Packet.h"
#include <string>
#include <unordered_map>
#include <vector>

//C# TO C++ CONVERTER NOTE: Forward class declarations:
namespace Server::MirDatabase { class PetInfo; }
namespace Server::MirDatabase { class FriendInfo; }
namespace Server::MirDatabase { class UserIntelligentCreature; }
namespace Server::MirDatabase { class MountInfo; }

using namespace Server::MirEnvir;
using namespace Server::MirNetwork;
using namespace Server::MirObjects;

namespace Server::MirDatabase
{
    class CharacterInfo
    {
    public:
        virtual ~CharacterInfo()
        {
            delete CurrentLocation;
            delete BindLocation;
            delete CurrentRefine;
            delete AccountInfo;
            delete Player;
            delete Mount;
        }

    protected:
        static Server::MirEnvir::Envir *getEnvir();

    public:
        int Index = 0;
        std::string Name;
        unsigned short Level = 0;
        MirClass Class = static_cast<MirClass>(0);
        MirGender Gender = static_cast<MirGender>(0);
        unsigned char Hair = 0;
        int GuildIndex = -1;

        std::string CreationIP;
        DateTime CreationDate;

        bool Banned = false;
        std::string BanReason = std::string::Empty;
        DateTime ExpiryDate;

        bool ChatBanned = false;
        DateTime ChatBanExpiryDate;

        std::string LastIP = std::string::Empty;
        DateTime LastLogoutDate;
        DateTime LastLoginDate;

        bool Deleted = false;
        DateTime DeleteDate;

        //Marriage
        int Married = 0;
        DateTime MarriedDate;

        //Mentor
        int Mentor = 0;
        DateTime MentorDate;
        bool isMentor = false;
        long long MentorExp = 0;

        //Location
        int CurrentMapIndex = 0;
        Point *CurrentLocation;
        MirDirection Direction = static_cast<MirDirection>(0);
        int BindMapIndex = 0;
        Point *BindLocation;

        int HP = 0, MP = 0;
        long long Experience = 0;

        AttackMode AMode = static_cast<AttackMode>(0);
        PetMode PMode = static_cast<PetMode>(0);
        bool AllowGroup = false;
        bool AllowTrade = false;

        int PKPoints = 0;

        bool NewDay = false;

        bool Thrusting = false, HalfMoon = false, CrossHalfMoon = false;
        bool DoubleSlash = false;
        unsigned char MentalState = 0;
        unsigned char MentalStateLvl = 0;

        std::vector<UserItem*> Inventory = std::vector<UserItem*>(46), Equipment = std::vector<UserItem*>(14), Trade = std::vector<UserItem*>(10), QuestInventory = std::vector<UserItem*>(40), Refine = std::vector<UserItem*>(16);
        std::vector<ItemRentalInformation*> RentedItems = std::vector<ItemRentalInformation*>();
        std::vector<ItemRentalInformation*> RentedItemsToRemove = std::vector<ItemRentalInformation*>();
        bool HasRentedItem = false;
        UserItem *CurrentRefine = nullptr;
        long long CollectTime = 0;
        std::vector<UserMagic*> Magics = std::vector<UserMagic*>();
        std::vector<PetInfo*> Pets = std::vector<PetInfo*>();
        std::vector<Buff*> Buffs = std::vector<Buff*>();
        std::vector<Poison*> Poisons = std::vector<Poison*>();
        std::vector<MailInfo*> Mail = std::vector<MailInfo*>();
        std::vector<FriendInfo*> Friends = std::vector<FriendInfo*>();

        //IntelligentCreature
        std::vector<UserIntelligentCreature*> IntelligentCreatures = std::vector<UserIntelligentCreature*>();
        int PearlCount = 0;

        std::vector<QuestProgressInfo*> CurrentQuests = std::vector<QuestProgressInfo*>();
        std::vector<int> CompletedQuests = std::vector<int>();

        std::vector<bool> Flags = std::vector<bool>(Globals::FlagIndexCount);

        AccountInfo *AccountInfo;
        PlayerObject *Player;
        MountInfo *Mount;

        std::unordered_map<int, int> GSpurchases = std::unordered_map<int, int>();
        std::vector<int> Rank = std::vector<int>(2); //dont save this in db!(and dont send it to clients :p)

        CharacterInfo();

        CharacterInfo(ClientPackets::NewCharacter *p, MirConnection *c);

        CharacterInfo(BinaryReader *reader);

        void Save(BinaryWriter *writer);

        SelectInfo *ToSelectInfo();

        bool CheckHasIntelligentCreature(IntelligentCreatureType petType);
        int ResizeInventory();
    };

    class PetInfo
    {
    public:
        int MonsterIndex = 0;
        int HP = 0;
        unsigned int Experience = 0;
        unsigned char Level = 0, MaxPetLevel = 0;

        long long TameTime = 0;

        PetInfo(MonsterObject *ob);

        PetInfo(BinaryReader *reader);

        void Save(BinaryWriter *writer);
    };

    class MountInfo
    {
    public:
        PlayerObject *Player;
        short MountType = -1;

        virtual ~MountInfo()
        {
            delete Player;
        }

        bool getCanRide() const;
        bool getCanMapRide() const;
        bool getCanDungeonRide() const;
        bool getCanAttack() const;
        bool getSlowLoyalty() const;

        bool getHasMount() const;

    private:
        bool getRidingMount() const;
        void setRidingMount(bool value);

    public:
        std::vector<UserItem*> getSlots() const;


        MountInfo(PlayerObject *ob);
    };

    class FriendInfo
    {
    public:
        virtual ~FriendInfo()
        {
            delete _Info;
        }

    protected:
        static Server::MirEnvir::Envir *getEnvir();

    public:
        int Index = 0;

    private:
        CharacterInfo *_Info;
    public:
        CharacterInfo *getInfo() const;

        bool Blocked = false;
        std::string Memo;

        FriendInfo(CharacterInfo *info, bool blocked);

        FriendInfo(BinaryReader *reader);

        void Save(BinaryWriter *writer);

        ClientFriend *CreateClientFriend();
    };

    class IntelligentCreatureInfo
    {
    public:
        static std::vector<IntelligentCreatureInfo*> Creatures;

        IntelligentCreatureType PetType = static_cast<IntelligentCreatureType>(0);

        int Icon = 0;
        int MinimalFullness = 1000;

        bool MousePickupEnabled = false;
        int MousePickupRange = 0;
        bool AutoPickupEnabled = false;
        int AutoPickupRange = 0;
        bool SemiAutoPickupEnabled = false;
        int SemiAutoPickupRange = 0;

        bool CanProduceBlackStone = false;

    private:
        class StaticConstructor
        {
        public:
            StaticConstructor();
        };

    private:
        static IntelligentCreatureInfo::StaticConstructor staticConstructor;


    public:
        IntelligentCreatureInfo();

        static IntelligentCreatureInfo *GetCreatureInfo(IntelligentCreatureType petType);
    };
    class UserIntelligentCreature
    {
    public:
        IntelligentCreatureType PetType = static_cast<IntelligentCreatureType>(0);
        IntelligentCreatureInfo *Info;
        IntelligentCreatureItemFilter *Filter;

        IntelligentCreaturePickupMode petMode = IntelligentCreaturePickupMode::SemiAutomatic;

        std::string CustomName;
        int Fullness = 0;
        int SlotIndex = 0;
        DateTime Expire;
        long long BlackstoneTime = 0;
        long long MaintainFoodTime = 0;

        virtual ~UserIntelligentCreature()
        {
            delete Info;
            delete Filter;
        }

        UserIntelligentCreature(IntelligentCreatureType creatureType, int slot, unsigned char effect = 0);

        UserIntelligentCreature(BinaryReader *reader);

        void Save(BinaryWriter *writer);

        Packet *GetInfo();

        ClientIntelligentCreature *CreateClientIntelligentCreature();
    };
}
